package cn.mini.mybatis.mybatis.builder.xml;

import cn.mini.mybatis.mybatis.builder.BaseBuilder;
import cn.mini.mybatis.mybatis.builder.MapperBuilderAssistant;
import cn.mini.mybatis.mybatis.mapping.BoundSql;
import cn.mini.mybatis.mybatis.mapping.SqlCommandType;
import cn.mini.mybatis.mybatis.session.Configuration;
import org.dom4j.Element;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * XMLStatementBuilder 类用于解析 XML 文件中的 SQL 语句节点（如 select、insert、update、delete），
 * 并将解析结果封装成 MappedStatement 对象添加到配置中。
 */
public class XMLStatementBuilder extends BaseBuilder {
    private Element element;
    private MapperBuilderAssistant builderAssistant;

    // 该正则表达式用于匹配SQL模板中的占位符 #{}，例如：
    // 在 SQL 语句中形如：SELECT * FROM users WHERE id = #{id} AND name = #{name}
    // 正则会匹配到 "#{id}" 和 "#{name}"，并捕获其中的变量名供后续替换为 ? 并构建参数映射
    Pattern pattern = Pattern.compile("(#\\{(.*?)})");


    public XMLStatementBuilder(Configuration configuration, MapperBuilderAssistant builderAssistant, Element element) {
        super(configuration);
        this.builderAssistant = builderAssistant;
        this.element = element;
    }

    public void parseStatementNode() {
        String id = element.attributeValue("id");
        String sql = element.getTextTrim();
        // 参数类型
        String parameterType = element.attributeValue("parameterType");
        // 结果类型
        String resultType = element.attributeValue("resultType");
        Class<?> resultTypeClass = resolveAlias(resultType);
        // 获取命令类型(select|insert|update|delete)
        String nodeName = element.getName();
        SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
        // 解析sql #{} 这样的形式需要解析
        Map<Integer,String > parameter = new HashMap<>();
        // 解析sql
        Matcher matcher = pattern.matcher(sql);
        for (int i = 1; matcher.find(); i++) {
            String content = matcher.group(1);
            String paramName = matcher.group(2);
            parameter.put(i, paramName);
            sql = sql.replace(content, "?");
        }
        BoundSql boundSql = new BoundSql(sql, parameter, parameterType, resultType);
        // 调用助手类
        builderAssistant.addMappedStatement(id,
                sqlCommandType,
                 boundSql,resultTypeClass);
    }
}
